﻿using System.Text;
using System.Xml;
using Coldairarrow.Util;
using Newtonsoft.Json;

namespace Gateway.Common.Extensions
{
    public static class StringExtensions
    {
        public static string ToMobileString(this string value)
        {
            return value.ToStarString(3, 4, 11);
        }

        public static string ToIdNumberString(this string value)
        {
            return value.ToStarString(3, 2, 18);
        }

        public static List<string> ToSplitList(this string value, string separator)
        {
            return value.ToSplitList(separator.ToCharArray());
        }

        public static List<string> ToSplitList(this string value, char[] separator)
        {
            return value.Split(separator, StringSplitOptions.RemoveEmptyEntries).ToList();
        }

        /// <summary>
        /// 生成0-9随机数
        /// </summary>
        /// <param name="codeNum">生成长度</param>
        /// <returns></returns>
        public static string GetRndNum(int codeNum = 5)
        {
            StringBuilder sb = new StringBuilder(codeNum);
            Random rand = new Random();
            for (int i = 1; i < codeNum + 1; i++)
            {
                int t = rand.Next(9);
                sb.AppendFormat("{0}", t);
            }
            return sb.ToString();
        }

        public static string GetRandomString(int len = 5)
        {
            if (len > 32) len = 32;
            if (len < 0) len = 5;
            return Guid.NewGuid().ToString("N").Substring(0, len);
        }

        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        public static string ToUrlString(this SortedDictionary<string, string> value, List<string> exceptKeys = null, Func<string, string> func = null)
        {
            var list = new List<string>();
            if (exceptKeys == null)
                exceptKeys = new List<string>();

            foreach (var item in value)
                if (!string.IsNullOrWhiteSpace(item.Value) && !exceptKeys.Contains(item.Key))
                {
                    var val = func?.Invoke(item.Value) ?? item.Value;
                    list.Add($"{item.Key}={val}");
                }
            return string.Join("&", list);
        }

        public static T GetModelFromXml<T>(this string value)
        {
            var dict = value.GetDictFromXml();
            try
            {
                return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(dict));
            }
            catch
            {
                return default;
            }
        }

        public static SortedDictionary<string, string> GetDictFromXml(this string value)
        {
            var doc = new XmlDocument();
            doc.LoadXml(value);

            var root = doc.GetElementsByTagName("xml")[0];
            if (root == null)
                return default;

            var list = root.ChildNodes;
            var dict = new SortedDictionary<string, string>();

            foreach (XmlNode item in list)
                dict.Add(item.Name, item.InnerText);

            return dict;
        }

        private static string ToStarString(this string value, int preNum, int afterNum, int formatLen = 0)
        {
            if (!string.IsNullOrWhiteSpace(value) && value.Length > (preNum + afterNum))
            {
                if (formatLen == 0)
                    formatLen = value.Length;

                var _pre = value.Substring(0, preNum);
                var _after = value.Substring(value.Length - afterNum);
                var _starNum = formatLen - (preNum + afterNum);
                var _str = string.Empty;

                if (_starNum <= 0)
                    _ = 0;
                else
                    for (int i = 0; i < _starNum; i++)
                        _str += "*";

                return $"{_pre}{_str}{_after}";
            }

            return value;
        }

        public static string ToUrlWithProto(this string value, string proto = "https")
        {
            if (!string.IsNullOrWhiteSpace(value)
                && !value.ToLower().StartsWith("http")
                && !value.ToLower().StartsWith("https"))
                return $"{proto}:{value}";
            return value;
        }

        /// <summary>
        /// 字符串转时间类型
        /// </summary>
        /// <param name="value">时间格式字符串</param>
        /// <param name="defValue">默认返回值</param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string value, DateTime? defValue = null)
        {
            var result = DateTime.TryParse(value, out DateTime time);
            if (result)
            {
                return time;
            }
            else
            {
                if (defValue.HasValue)
                {
                    return defValue.Value;
                }
                else
                {
                    return DateTime.Now;
                }
            }
        }

        /// <summary>
        /// 字符串转时间类型
        /// </summary>
        /// <param name="dateTimeStr"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string value)
        {
            var result = DateTime.TryParse(value, out DateTime dateTime);
            if (result)
            {
                return dateTime;
            }
            else
            {
                return DateTime.MinValue;
            }
        }


        /// <summary>
        /// 将对象转化为json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToJson<T>(this T obj)
        {
            return JsonConvert.SerializeObject(obj);
        }

        /// <summary>
        /// 将json转化为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T ToObj<T>(this string json)
        {
            try
            {
                return JsonConvert.DeserializeObject<T>(json); ;
            }
            catch (Exception)
            {
                return default(T);
            }
        }
        #region 雪花ID

        public static string ToSnowFlakeNoString(this string value)
        {
            return $"{value}{IdHelper.GetId()}";
        }

        public static string GetSnowFlakeIdString()
        {
            return IdHelper.GetId();
        }

        public static long GetSnowFlakeId()
        {
            return IdHelper.GetLongId();
        }

        #endregion
        
        
        public static string ToPath(this string s)
        {
            if (string.IsNullOrEmpty(s))
                return string.Empty;

            return s.Replace(@"\", "/");
        }
        
        
        
        /// <summary>
        /// 毫秒转天时分秒
        /// </summary>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static string FormatTime(long ms)
        {
            int ss = 1000;
            int mi = ss * 60;
            int hh = mi * 60;
            int dd = hh * 24;

            long day = ms / dd;
            long hour = (ms - day * dd) / hh;
            long minute = (ms - day * dd - hour * hh) / mi;
            long second = (ms - day * dd - hour * hh - minute * mi) / ss;
            long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

            string sDay = day < 10 ? "0" + day : "" + day; //天
            string sHour = hour < 10 ? "0" + hour : "" + hour;//小时
            string sMinute = minute < 10 ? "0" + minute : "" + minute;//分钟
            string sSecond = second < 10 ? "0" + second : "" + second;//秒
            string sMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒
            sMilliSecond = milliSecond < 100 ? "0" + sMilliSecond : "" + sMilliSecond;

            return string.Format("{0} 天 {1} 小时 {2} 分 {3} 秒", sDay, sHour, sMinute, sSecond);
        }


        /// <summary>
        /// 获取到本地的Json文件并且解析返回对应的json字符串
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static string GetJsonFile(this string filepath)
        {
            string json = string.Empty;
            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                //Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                using (StreamReader sr = new StreamReader(fs))
                {
                    json = sr.ReadToEnd().ToString();
                }
            }
            return json;
        }


        /// <summary>
        /// 获取到本地的Json文件并且解析返回对应的json字符串
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static T ParseJsonFile<T>(this string filepath)
        {
            string json = filepath.GetJsonFile();
            if (string.IsNullOrEmpty(json))
                return default(T);
            return JsonConvert.DeserializeObject<T>(json);
        }
    }
}